import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

public class Lamda序列化的坑 {
    public static void main(String[] args) throws Exception {

        // -Djdk.internal.lambda.dumpProxyClasses=D:/t 将lambda类dump到磁盘
        // lambda类生成是依赖一些工厂类的: InnerClassLambdaMetafactory
        // https://www.zhihu.com/question/51491241/answer/126232275
        VoidFun<String> f1 = s -> System.out.println(s);  // 正常
        VoidFun<String> f2 = System.out::println;   // 报错

        PrintStream stream = System.out;
        VoidFun<String> f3 = s -> stream.println(s); // 报错



        ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream());
        oos.writeObject(f1);
    }


    public static interface VoidFun<T> extends Serializable {
        void apply(T t);

    }

    private static void check(Function... functions) {
        for (Function fun : functions) {
            System.out.println("传入的实现类：" + fun.getImplClass());
            System.out.println("传入的方法名：" + fun.getImplMethodName());
            System.out.println("传入的参数值：" + fun.get());
            System.out.println("传入数据类型：" + fun.get().getClass());
        }
    }

    @FunctionalInterface
    public static interface Function extends Serializable {
        //这里只接收无参方法
        Object get();

        //这个方法返回的SerializedLambda是重点
        default SerializedLambda getSerializedLambda() throws Exception {
            //writeReplace改了好像会报异常
            Method write = this.getClass().getDeclaredMethod("writeReplace");
            write.setAccessible(true);
            return (SerializedLambda) write.invoke(this);
        }

        default String getImplClass() {
            try {
                return getSerializedLambda().getImplClass();
            } catch (Exception e) {
                return null;
            }
        }

        default String getImplMethodName() {
            try {
                return getSerializedLambda().getImplMethodName();
            } catch (Exception e) {
                return null;
            }
        }
    }

}
